package seatiger.tomcat.catalina.connector.http;

import seatiger.tomcat.catalina.Constants;
import seatiger.tomcat.util.StringManager;

import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
@Deprecated
public class SocketInputStream extends InputStream {
    /**
     * 与客户端建立连接之后的InputStream
     */
    protected InputStream is;
    /**
     * 将客户读取的数据封住到 字节数组中
     */
    protected byte buf[];

    private static final byte CR = (byte) '\r';
    private static final byte LF = (byte) '\n';
    private static final byte SP = (byte) ' ';
    private static final byte COLON = (byte) ':';
    private static final int LC_OFFSET = 'A' - 'a';
    private static final byte HT = (byte) '\t';
    protected int pos;
    protected int count;

    protected static StringManager sm =
            StringManager.getManager(Constants.PACKAGE_CONNECTOR);


    public SocketInputStream(InputStream is,int bufferSize) {
        this.is = is;
        buf = new byte[bufferSize];
    }

    /**
     * 读取数据解析请求行
     * @param requestLine
     */
    public void readRequestLine(HttpRequestLine requestLine) throws IOException {
        //初始化
        if (requestLine.methodEnd != 0) {
            requestLine.recycle();
        }
        int chr = 0;
        //过滤首部的回车换行
        do {
            try {
                chr = read();
            }catch (Exception e){
                chr = -1;
            }
        } while ((chr == CR) || (chr == LF));
        if (chr == -1){
            throw new EOFException
                    (sm.getString("requestStream.readline.error"));
        }
        //将位置还原
        pos--;
        readMethodName(requestLine);
        readUri(requestLine);
        readProtocol(requestLine);
    }

    /**
     * 读取请求头
     * @param header
     */
    public void readHeader(HttpHeader header) throws IOException{
        if (header.nameEnd != 0){
            header.recycle();
        }
        if (!haveNextHead(header)){
            return;
        }
        pos--;
        readHeadName(header);
        readHeadValue(header);
    }

    private void readHeadValue(HttpHeader header) throws IOException{
        boolean space = true;
        //将 : 后面的 空格去除
        while (space) {
            needRead();
            //空格和 tab全部去除
            if ((buf[pos] == SP) || (buf[pos] == HT)){
                pos++;
            }else {
                space = false;
            }
        }
        boolean eol = false;
        int readCount = 0;
        while (!eol) {
            needRead();
            if (buf[pos] == CR){
            }else if(buf[pos] == LF){
                eol = true;
            }else {
                header.value[readCount] = (char) buf[pos];
                readCount++;
            }
            pos++;
        }
        header.valueEnd = readCount;
    }

    /**
     * 读取headName
     * @param header
     */
    private void readHeadName(HttpHeader header) throws IOException{
        boolean colon = false;
        int readCount = 0;
        while (!colon) {
            needRead();
            if (buf[pos] == COLON){
                colon = true;
            }
            char val = (char) buf[pos];
            if ((val >= 'A') && (val <= 'Z')) {
                //将大写的字符转为小写的
                val = (char) (val - LC_OFFSET);
            }
            header.name[readCount] = val;
            readCount++;
            pos++;
        }
        header.nameEnd = readCount - 1;
    }

    /**
     * 判断是否还有报文头
     * @return
     */
    public boolean haveNextHead(HttpHeader header) throws IOException{
        //看一下是否有必要在读取一下数据
        //如果pos的位置已经在buf有效数据最后一位，那么需要再读取一下数据
        //不管是否读取数据， 返回的是当前pos 位置上的值，并 将pos往后挪了一位
        int chr = read();
        //如果是回车换行，那么就说明head中已经没有数据了
        if ((chr == CR) || (chr == LF)){
            // GET /test HTTP/1.1/r/n
            // headName1: headValue2/r/n
            // headName2: headValue3/r/n
            // /r/n
            // body (pos的)位置
            if (chr == CR) {
                //如果是回车，调过 换行
                read();
            }
            header.nameEnd = 0;
            header.valueEnd = 0;
            return false;
        }
        return true;
    }

    private int readMethodName(HttpRequestLine requestLine) throws IOException{
        //读取的数量
        int readCount =0;
        //空格作为分隔符
        boolean space = false;
        while (!space){
            needRead();
            //读取到了空格，那么就读取到了方法
            if (buf[pos] == SP){
                space = true;
            }
            //将每个buf中的值，复制到method[] 数组中
            requestLine.method[readCount] =(char)buf[pos];
            readCount++;
            pos++;
        }
        //method[] 数组中 有效的数据数量，就是method
        requestLine.methodEnd = readCount - 1;
        return pos;
    }

    /**
     * 读取uri
     * @param requestLine
     * @return
     * @throws IOException
     */
    private int readUri(HttpRequestLine requestLine) throws IOException{
        //读取的数量
        int readCount =0;
        //空格作为分隔符
        boolean space = false;
        while (!space){
            needRead();
            //读取到了空格，那么就读取到了uri
            if (buf[pos] == SP){
                space = true;
            }
            //将每个buf中的值，复制到method[] 数组中
            requestLine.uri[readCount] =(char)buf[pos];
            readCount++;
            pos++;
        }
        requestLine.uriEnd = readCount - 1;
        return pos;
    }

    /**
     * 读取 protocol
     * @param requestLine
     * @return
     * @throws IOException
     */
    private int readProtocol(HttpRequestLine requestLine) throws IOException {
        //读取的数量
        int readCount =0;
        //空格作为分隔符
        boolean eol = false;
        while (!eol){
            needRead();
            // 如果是回车，那么就跳过
            if (buf[pos] == CR){

            }else if (buf[pos] == LF){ //换行
                eol = true;
            }else{
                //将每个buf中的值，复制到method[] 数组中
                requestLine.protocol[readCount] =(char)buf[pos];
                readCount++;
            }
            pos++;
        }
        requestLine.protocolEnd = readCount;
        return pos;
    }


    @Override
    public int read() throws IOException {
        //当前解析到buf中的位置 已经大于等于总数了，说明已经解析到末尾了
        //需要重新读取数据
        if (pos >= count){
            fill();
            if (pos >= count){
                //已经读取到末尾了
                return -1;
            }
        }
        //将读取到的第一个字符返回，并把pos的位置+1
        return buf[pos++] & 0xff;
    }

    protected void fill() throws IOException {
        pos = 0;
        count = 0;
        int nRead = is.read(buf, 0, buf.length);
        if (nRead > 0){
            count = nRead;
        }
    }

    public void needRead() throws IOException{
        if (pos >= count) {
            int val = read();
            if (val == -1) {
                throw new IOException
                        ("requestStream.readline.error");
            }
            pos = 0;
        }
    }
}
